﻿using System;
using System.Collections.Generic;

namespace yunio.websocket
{
    internal partial class helper
    {
        public static bool Contains<T>(T[] arr, T item)
        {
            for (int i =0; i < arr.Length; i++) if (arr[i].Equals(item)) return true;
            return false;
        }
        public static int Count<T>(IEnumerable<T> arr, Where_IF<T> _if)
        {
            var count = 0;
            foreach (var item in arr) if (_if(item)) count++;
            return count;
        }
        public static T[] CloneRange<T>(T[] source, int offset, int length)
        {
            T[] values = new T[length];
            for(var i = 0; offset < length; offset++, i++) values[i] = source[offset];
            return values;
        }

        public delegate bool Where_IF<T>(T inobj);
        public static IEnumerable<T> Where<T>(T[] arr, Where_IF<T> _if)
        {
            for (var i = 0; i < arr.Length; i++) if (_if(arr[i])) yield return arr[i];  
        }
        public static T[] ToArray<T>(IEnumerable<T> arr)
        {
            var queue = new Queue<T>();
            foreach (var item in arr) queue.Enqueue(item);

            return queue.ToArray();
        }

        public delegate string ToDictionary_GetKey<T>(T inobj);
        public static Dictionary<string, T> ToDictionary<T>(T[] arr, ToDictionary_GetKey<T> _getkey)
        {
            var dict = new Dictionary<string, T>();
            for(var i = 0; i < arr.Length; i++) dict[_getkey(arr[i])] = arr[i];
            return dict;
        }
        public static bool Any<T>(IEnumerable<T> arr)
        {
            return arr.GetEnumerator().MoveNext();
        }
        public delegate int OrderBy_getval<T>(T inobj);
        public static T[] OrderBy<T>(IEnumerable<T> arr, OrderBy_getval<T> _getval)
        {
            var _arr = arr.GetEnumerator();
            if (!_arr.MoveNext()) return default;

            var raw = _arr.Current;
            int raw_val = _getval(raw);
            var queue_a = new Queue<T>();
            var queue_b = new Queue<T>();

            //冒泡排序
            while (_arr.MoveNext()) queue_a.Enqueue(_arr.Current);
            var ix = queue_a.Count + 1;
            var _out = new T[ix];
            ix--;

            while (queue_a.Count > 0 || queue_b.Count > 0)
            {
                while (queue_a.Count > 0)
                {
                    var i = queue_a.Dequeue();
                    if (_getval(i) > raw_val)
                    {
                        queue_b.Enqueue(raw);
                        raw = i;
                        raw_val = _getval(raw);
                    }
                    else queue_b.Enqueue(i);
                }
                _out[ix--] = raw;
                if (queue_b.Count > 0)
                {
                    if (queue_b.Count == 1)
                    {
                        _out[ix] = queue_b.Dequeue();
                        break;
                    }
                    raw = queue_b.Dequeue();
                    raw_val = _getval(raw);
                    while (queue_b.Count > 0)
                    {
                        var i = queue_b.Dequeue();
                        if (_getval(i) > raw_val)
                        {
                            queue_a.Enqueue(raw);
                            raw = i;
                            raw_val = _getval(i);
                        }
                        else queue_a.Enqueue(i);
                    }
                    _out[ix--] = raw;

                    if (queue_a.Count > 0)
                    {
                        if (queue_a.Count == 1)
                        {
                            _out[ix] = queue_a.Dequeue();
                            break;
                        }
                        raw = queue_a.Dequeue();
                        raw_val = _getval(raw);
                    }
                }
            }

            return _out;
        }
        public static T[] OrderByDescending<T>(IEnumerable<T> arr, OrderBy_getval<T> _getval)
        {
            var _arr = arr.GetEnumerator();
            if (!_arr.MoveNext()) return default;

            var raw = _arr.Current;
            int raw_val = _getval(raw);
            var queue_a = new Queue<T>();
            var queue_b = new Queue<T>();

            //冒泡排序
            while (_arr.MoveNext()) queue_a.Enqueue(_arr.Current);
            var ix = queue_a.Count + 1;
            var _out = new T[ix];
            ix--;

            while (queue_a.Count > 0 || queue_b.Count > 0)
            {
                while (queue_a.Count > 0)
                {
                    var i = queue_a.Dequeue();
                    if (_getval(i) < raw_val)
                    {
                        queue_b.Enqueue(raw);
                        raw = i;
                        raw_val = _getval(raw);
                    }
                    else queue_b.Enqueue(i);
                }
                _out[ix--] = raw;
                if (queue_b.Count > 0)
                {
                    if (queue_b.Count == 1)
                    {
                        _out[ix] = queue_b.Dequeue();
                        break;
                    }
                    raw = queue_b.Dequeue();
                    raw_val = _getval(raw);
                    while (queue_b.Count > 0)
                    {
                        var i = queue_b.Dequeue();
                        if (_getval(i) < raw_val)
                        {
                            queue_a.Enqueue(raw);
                            raw = i;
                            raw_val = _getval(i);
                        }
                        else queue_a.Enqueue(i);
                    }
                    _out[ix--] = raw;

                    if (queue_a.Count > 0)
                    {
                        if (queue_a.Count == 1)
                        {
                            _out[ix] = queue_a.Dequeue();
                            break;
                        }
                        raw = queue_a.Dequeue();
                        raw_val = _getval(raw);
                    }
                }
            }

            return _out;
        }
    }
}
